const Vue = require('vue');
const express = require("express");
const session = require("express-session");
const compression = require("compression");
const microcache = require('route-cache');
// const favicon = require('serve-favicon');
const LRU = require('lru-cache');
const bodyParser = require("body-parser");
const path = require("path");
const app = express();

const { createBundleRenderer } = require('vue-server-renderer');
const serverBundle = require('../dist/vue-ssr-server-bundle.json');
const clientManifest = require('../dist/vue-ssr-client-manifest.json');
const templatePath = path.resolve(__dirname, '../index.template.html');
const useMicroCache = process.env.MICRO_CACHE !== 'false';
const isProd = process.env.NODE_ENV == 'production';
const serverPort = '7033';

const serverInfo =
    `express/${require('express/package.json').version} ` +
    `vue-server-renderer/${require('vue-server-renderer/package.json').version}`;

const createRenderer = (bundle, options) => {
    return createBundleRenderer(bundle, Object.assign(options, {
        runInNewContext: false,
        inject: false,
        shouldPreload: (file) => {
            if(/(mainfest|vendors~main).css$/.test(file)){
                return false;
            }
            return true;
        },
        shouldPrefetch: (file) => {
            if(/(mainfest|vendors~main).css$/.test(file)){
                return false;
            }
            return true;
        },
        cache: new LRU({
            max: 1000,
            maxAge: 1000 * 60 * 15
        }),
        basedir: path.resolve(__dirname, "../dist")
    }))
};
const render = (req, res) => {
    const startDate = Date.now();

    res.setHeader('Content-Type', 'text/html');
    res.setHeader('Server', serverInfo);

    const handleError = err => {
        if(err.url){
            res.redirect(err.url);
        } else if(err.code === 404){
            res.status(404).send('404 | Page Not Found');
        } else {
            res.status(500).send('500 | Internal Server Error');
            console.log(`error render : ${req.url}`);
            console.log(err.stack);
        }
    }

    const context = {
        title: 'vue ssr',
        url: req.url
    };
    context.link = isProd ? `
        <link rel="stylesheet" href="/dist/css/main.css" >
    ` : ``;

    // const createApp = require('../dist/ssr.js').default;
    // createApp(context).then(a => {
    renderer.renderToString(context, (err, html) => {
        if(err){
            return handleError(err);
        }
        res.end(html);

        if(!isProd) {
            console.log(`whole request: ${Date.now() - startDate}ms`);
        }
    });
    // });

}

let renderer, readyPromise;
if(isProd) {
    renderer = createRenderer(serverBundle, {
        template: require('fs').readFileSync(templatePath, 'utf-8'),
        clientManifest
    });
} else {
    readyPromise = require('./devServer')(app, serverPort, templatePath, (bundle, options) => {
        renderer = createRenderer(bundle, options);
    });
}

var exdate = new Date();
exdate.setTime(exdate.getTime() + 10000000);
app.use(session({
    cookie: { maxAge: 10000},
    name: 'test',
    secret: 'lvhe',
    rolling: false,
    saveUninitialized: true,
    resave: true
}));

app.use(compression({threshold: 0}));
app.use(bodyParser.text());
app.use(bodyParser.json());
console.log("请求开始...");

const serve = (url, cache) => express.static(path.resolve(__dirname, url), {
    maxAge: cache && isProd ? 1000 * 60 * 60 * 24 * 30 : 0
})

app.use('/dist', serve("../dist", true));
app.use(function(err, req, res, next) {
    console.log("错误信息:", err);
    res.status(err.status || 500);
    res.json({
        message: err.message,
        error: app.get("env") === "development" ? err : {}
    });
});

app.use(microcache.cacheSeconds(1, req => useMicroCache && req.originalUrl));
app.get('*', isProd ? render : (req, res) => {
    readyPromise.then(() => {
        render(req, res);
    })
});

app.disable("x-powered-by");
const server = app.listen(serverPort, () => {
    const {port} = server.address();
    console.log(`Listened at http://localhost:${port}`);
});